package com.xdcplus.web.service.minio.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.xdcplus.exceptions.XdcWebException;
import com.xdcplus.mom.constants.MinioConstant;
import com.xdcplus.mom.enums.ResponseEnum;
import com.xdcplus.web.service.minio.MinioService;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @Description
 * @Author Devin.sang
 * @Date 2023/5/7 16:26
 */

@Service
public class MinioServiceImpl implements MinioService {

    @Autowired
    protected MinioClient minioClient;

    @Override
    public String uploadFile(MultipartFile file) {

        String originalFilename = file.getOriginalFilename();
        if (ObjectUtil.isEmpty(originalFilename)){
            throw new XdcWebException(ResponseEnum.FILE_ISBLANK);
        }

        String filename = UuidUtils.generateUuid() + originalFilename.substring(originalFilename.lastIndexOf("."));
        try {
            PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(MinioConstant.LOG_BUCKET_NAME).object(filename)
                    .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
            //文件名称相同会覆盖
            minioClient.putObject(objectArgs);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return previewFile(filename);


    }

    @Override
    public String previewFile(String filename) {
        // 查看文件地址
        GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(MinioConstant.LOG_BUCKET_NAME).object(filename).method(Method.GET).build();
        try {
            String url = minioClient.getPresignedObjectUrl(build);
            return url;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public GetObjectResponse pullFile(String filename) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        GetObjectArgs objectUrlArgs = GetObjectArgs.builder()
                .bucket(MinioConstant.CRAFT_BUCKET_NAME)
                .object(filename).build();
        return minioClient.getObject(objectUrlArgs);
    }

    @Override
    public String previewFile(String bucket,String filename) {
        // 查看文件地址
        GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(bucket).object(filename).method(Method.GET).build();
        try {
            String url = minioClient.getPresignedObjectUrl(build);
            return url;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String uploadText(String message) {

        if (message != null) {
            ByteArrayOutputStream bufferedOutputStream = new ByteArrayOutputStream();
            try {

                /// 编码格式? 指明编码格式，读写必须一致。
                bufferedOutputStream.write(message.getBytes(Charset.forName("GB2312")));
                ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
                        bufferedOutputStream.toByteArray()
                );

                Snowflake snowflake = new Snowflake();
                /// 存储 text/plain 类型，前端iframe可以直接访问
                String filename = snowflake.nextIdStr() + "_" + RandomUtil.randomNumbers(6) + ".txt";
                LocalDateTime localDateTime = LocalDateTime.now();
                filename = String.format("%s/%s/%s/%s",
                        localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                        ,localDateTime.getHour()
                        ,localDateTime.getMinute()
                        ,filename);

                PutObjectArgs objectArgs = PutObjectArgs.builder()
                        .bucket(MinioConstant.LOG_BUCKET_NAME).object(filename)
                        .stream(
                                byteArrayInputStream,
                                message.getBytes(Charset.forName("GB2312")).length,
                                -1).

                        contentType(MediaType.TEXT_PLAIN_VALUE)
                        .build();

                //文件名称相同会覆盖
                minioClient.putObject(objectArgs);
                String url = previewFile(filename);
                return url.substring(0,url.indexOf("?"));

            } catch (Throwable throwable) {
                throwable.printStackTrace();
                return message;
            }
        }
        return message;
    }

    @Override
    public void downloadFile(String filename, HttpServletResponse resp) {
        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(MinioConstant.LOG_BUCKET_NAME)
                .object(filename).build();
        try (GetObjectResponse response = minioClient.getObject(objectArgs)){
            byte[] buf = new byte[1024];
            int len;
            try(FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
                while ((len=response.read(buf))!=-1){
                    os.write(buf,0,len);
                }
                os.flush();
                byte[] bytes = os.toByteArray();
                resp.setCharacterEncoding("utf-8");
                resp.addHeader("Content-Disposition", "attachment;fileName=" + filename);

                try(ServletOutputStream stream = resp.getOutputStream()){
                    stream.write(bytes);
                    stream.flush();
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



}
